import socket
import threading


class SniffingPort:
    def __init__(self):
        self.tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp.settimeout(0.5)

    def port_only(self, ip, port, info='未定义'):
        """
        :return:None 提供单查询
        """
        try:
            # 返回一个整数，如果返回是0的话那么就代表他开放了此服务
            result = self.tcp.connect_ex((ip, int(port)))
            if result == 0:
                print("open>>>>[*%s*]>>>>>[# 端口描述:%s #]" % (port, info))
                # self.tcp.close()
                return 0
        except socket.error as e:
            print("error", e)

    def port_all(self, ip, port_size=(1, 65535), is_all=False):
        """扫描指定端口或全部端口"""
        if is_all:
            port_min, port_max = port_size
            for i in range(port_min, port_max + 1):
                threading.Thread(target=self.port_only, args=(ip, i)).start()
            return True
        # 开始对默认的端口进行扫描
        default = self.common_port()
        for k, v in default.items():
            threading.Thread(target=self.port_only, args=(ip, k, v)).start()

    def __del__(self):
        self.tcp.close()
        print('端口扫描已关闭')

    def common_port(self):
        """作为默认值扫描常见的端口服务"""
        arr = {
            80: 'hhtp网站默认',
            22: 'ssh远程登录',
            21: 'ftp远程文件上传',
            3306: 'mysql数据库',
            443: 'SSL证书',
            3389: 'windows remote　远程桌面',
            8888: '宝塔集成',
            7778: 'system admin login',
            445: 'SMB',
            1433: 'MSSQL数据库',
            1521: 'Oracle数据库',
            5432: 'Post greSQL数据库',
            6379: 'redis未授权',
            7001: 'web logic默认弱口令 反序列',
            7002: 'web logic默认弱口令　反序列'

        }
        return arr


if __name__ == '__main__':
    # 函数测试
    port_object = SniffingPort()
    port_object.port_all('192.168.69.78', port_size=(80, 500), is_all=True)
